package com.demo.common.excel;

import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.FormulaError;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Slf4j
public class CellMergeStrategy extends AbstractMergeStrategy {

    private long size;
    private long total;
    private long currentTotal;

    private Set<String> compareFields;

    private Set<String> mergeFields;

    private Integer rowMergeStart;

    private List<String> compareDataLine=new ArrayList<>();

    private List<String> currentDataLine=new ArrayList<>();

    private Integer currentRow;

    private Boolean needMerge=false;

    private Boolean currentLineChecked=false;

    private int lineMergedFields=0;

    private Boolean endSave=false;

    public CellMergeStrategy(long total,long size,List<String> compareFields, List<String> mergeFields){
        this.total=total;
        this.size=size;
        this.compareFields=new HashSet<>(compareFields);
        this.mergeFields=new HashSet<>(mergeFields);
        CellMergeStrategy cellMergeStrategy = ExcelUtils.getCellMergeStrategy();
        if(cellMergeStrategy!=null){
            this.currentTotal=cellMergeStrategy.currentTotal;
            this.rowMergeStart=cellMergeStrategy.rowMergeStart;
            this.compareDataLine=cellMergeStrategy.compareDataLine;
            this.currentDataLine=cellMergeStrategy.currentDataLine;
            this.currentRow= cellMergeStrategy.currentRow;;
            this.needMerge=cellMergeStrategy.needMerge;
            this.currentLineChecked=cellMergeStrategy.currentLineChecked;
            this.lineMergedFields=cellMergeStrategy.lineMergedFields;
        }
    }

    @Override
    protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
        if(rowMergeStart==null){
            rowMergeStart=cell.getRowIndex();
        }
        if(currentRow==null){
            currentRow=cell.getRowIndex();
            currentTotal++;
        }
        int rowIndex = cell.getRowIndex();
        if(currentRow!=rowIndex){
            //换行重置check
            currentLineChecked=false;
            currentDataLine.clear();
            currentRow=rowIndex;
            currentTotal++;
        }
        //第一行
        if(compareDataLine.size()<compareFields.size()){
            if(compareFields.contains(head.getFieldName())){
                log.info("对比字段{}值{}",head.getFieldName(),getStringValue(cell));
                compareDataLine.add(getStringValue(cell));
            }
            if(compareDataLine.size()==compareFields.size()){
                currentLineChecked=true;
            }
            return;
        }
        if(currentLineChecked){
            return;
        }
        if(currentDataLine.size()<compareFields.size()){
            if(compareFields.contains(head.getFieldName())){
                log.info("当前字段{}值{}",head.getFieldName(),getStringValue(cell));
                currentDataLine.add(getStringValue(cell));
            }
            if(currentDataLine.size()==compareDataLine.size()){
                if(!compareDataLine.equals(currentDataLine)){
                    //1行就不合并
                    if(rowMergeStart+1==currentRow){
                        compareDataLine.clear();
                        compareDataLine.addAll(currentDataLine);
                        currentDataLine.clear();
                        rowMergeStart= cell.getRowIndex();
                        currentLineChecked=true;
                    }else{
                        needMerge=true;
                    }
                }else if(currentTotal==total){
                    //最后一行也合并
                    needMerge=true;
                }else {
                    //不合并,不检查后续
                    currentDataLine.clear();
                    currentLineChecked=true;
                }
            }
            return;
        }
        if(needMerge){
            //标记合并的
            if(mergeFields.contains(head.getFieldName())){
                int lastRowIndex=cell.getRowIndex()-1;
                if(currentTotal==total&&currentDataLine.equals(compareDataLine)){
                    lastRowIndex=cell.getRowIndex();
                }
                sheet.addMergedRegionUnsafe(
                        new CellRangeAddress(rowMergeStart, lastRowIndex, cell.getColumnIndex(),
                                cell.getColumnIndex()));
                lineMergedFields++;
                //合并完了
                if(lineMergedFields==mergeFields.size()){
                    needMerge=false;
                    compareDataLine.clear();
                    compareDataLine.addAll(currentDataLine);
                    currentDataLine.clear();
                    lineMergedFields=0;
                    rowMergeStart= cell.getRowIndex();
                    currentLineChecked=true;
                    //当前查询最后一页了
                    if(currentTotal%size==0&&!endSave){
                        ExcelUtils.setCellMergeStrategy(this);
                        endSave=true;
                    }
                }
            }
        }else{
            //当前查询最后一页了
            if(currentTotal%size==0&&!endSave){
                ExcelUtils.setCellMergeStrategy(this);
                endSave=true;
            }
        }

    }

    /**
     * 转string
     */
    private String getStringValue(Cell cell) {
        CellType cellType = cell.getCellTypeEnum();
        switch (cellType) {
            case BLANK:
                return "";
            case BOOLEAN:
                return cell.getBooleanCellValue() ? "true" : "false";
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                return Double.toString(cell.getNumericCellValue());
            case ERROR:
                byte errVal = cell.getErrorCellValue();
                return FormulaError.forInt(errVal).getString();
            default:
                throw new IllegalStateException("Unexpected cell type (" + cellType + ")");
        }
    }

}